package com.zte.claa.inficombo.csa.app.service.devpower.impl;


import java.sql.Timestamp;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.zte.claa.inficombo.csa.app.config.RedisChannelProps;
import com.zte.claa.inficombo.csa.app.model.devpower.DevPowerBase;
import com.zte.claa.inficombo.csa.app.model.redis.AlarmData;
import com.zte.claa.inficombo.csa.app.model.redis.DevMeteData;
import com.zte.claa.inficombo.csa.app.service.cache.CacheRedisManager;
import com.zte.claa.inficombo.csa.app.service.csa.impl.BaseCacheManager;
import com.zte.claa.inficombo.csa.app.service.devpower.DevPowerConverter;
import com.zte.claa.inficombo.csa.app.service.devpower.DevPowerDataService;
import com.zte.claa.inficombo.csa.app.service.redis.CSAMessagePublisher;
import com.zte.claa.inficombo.csa.app.util.AlarmUtils;
import com.zte.claa.inficombo.csa.app.util.JsonUtils;
import com.zte.claa.inficombo.csa.app.util.LocUtils;




@Service
public class DevPowerDataServiceImpl implements DevPowerDataService,InitializingBean {

	private static final Logger logger = LoggerFactory.getLogger(DevPowerDataServiceImpl.class);
	
	private static final String LOW_POWER_ALARM_CODE = "3";
	
	private static final String LOW_POWER_ALARM_DESC = "低电量报警";
	
	private static final String NORMAL_POWER_DESC = "低电量报警恢复正常";
	
	//当前电压key
	private static final String CUR_VOLTAGE = "curvoltage";
	//累计电量key
	private static final String POWER_CON_SUM = "powerconsum";
	
	private static final String CUR_POWER_PERCENT= "curpowerpercent";
	
	private static final float DEFAULT_LOW_POWER_THRESHOLD = 30f;	
	//电量恢复阈值
	private static final float DEFAULT_NORMAL_POWER_THRESHOLD = 80f;
	
	private static final double INVALID_THRESHOLD = 0.1d; //电压或电量无效阈值
	//电压类型
	private static final byte  TYPE_VOL = 1;
	//累计电量类型
	private static final byte  TYPE_SUM_Q = 2;
	//电压等级类型
	private static final byte  TYPE_LEVEL = 4;
	//报警标志
	private static final Integer ALARM_FLAG = 0;
	//报警恢复标志
	private static final Integer ALARM_CLEAR_FLAG = 1;
	
	private CSAMessagePublisher	alarmPublisher;
	
	@Autowired
	private CacheRedisManager cacheRedisManager;
	
	@Autowired
	private StringRedisTemplate redisStrTemplate;
	
	@Autowired
	private RedisChannelProps redisChannelProps;
	
	@Autowired
	private BaseCacheManager cacheManager;
	
	@Override
	public void afterPropertiesSet() throws Exception {
		this.alarmPublisher = new CSAMessagePublisher(this.redisStrTemplate, this.redisChannelProps.getAlarmrptchannel());		
	}
	
	@Override
	public void processDevPowerData(List<DevMeteData> dataList) {
		if(dataList == null || dataList.size() == 0){
			return;
		}
		
		try{
			List<DevPowerBase> list = cacheRedisManager.getDevPowerBaseByDev(dataList.get(0).getDeveui());
			if(list == null || list.size() ==0){
				return;
			}
			//电量计算配置信息
			DevPowerBase base = list.get(0);
			byte checkFlag = base.getPowercheckway();
			Float lowPowerThreshold = base.getLowpowerthreshold();
			if(lowPowerThreshold == null){
				lowPowerThreshold = DEFAULT_LOW_POWER_THRESHOLD;
			}
			
			//获取转换器
			DevPowerConverter converter = base.getConverter();
			if(converter == null){
				return;
			}
			
			int q = 0;	
			Object obj = null;
			Iterator<DevMeteData> it = dataList.iterator();			
			while(it.hasNext()){
				DevMeteData mete = it.next();			
				Map<String, Object> map = mete.getMdata();
				if(map == null){
					it.remove();
					continue;
				}
								
				if(checkFlag == TYPE_VOL){//根据电压
					obj = map.get(CUR_VOLTAGE);
					if(obj == null){
						it.remove();
						continue;
					}else{
						double ret = Double.parseDouble(obj.toString());
						if(ret < INVALID_THRESHOLD){//如果是无效的电压值,删除当前项
							it.remove();
							continue;
						}else{
							q = converter.v2qConverter(ret);
						}						
					}						
				}else if(checkFlag == TYPE_SUM_Q){//根据用电累积量
					obj = map.get(POWER_CON_SUM);
					if(obj == null){
						it.remove();
						continue;
					}else{
						double ret = Double.parseDouble(obj.toString());
						if(ret < INVALID_THRESHOLD){//如果是无效的电量值,删除当前项
							it.remove();
							continue;
						}else{
							q = converter.a2qConverter(ret);		
						}				
					}			
				}else if(checkFlag == TYPE_LEVEL){//根据电压等级
					obj = map.get(CUR_VOLTAGE);	
					if(obj == null){
						it.remove();
						continue;
					}else{
						double ret = Double.parseDouble(obj.toString());
						q = converter.l2qConverter(ret);		
					}						
				}				
				map.put(CUR_POWER_PERCENT, q);
				logger.info("processDevPowerData MeteData is: {}",mete);
				//判定是否需要报警
				judgeDevPowerAlarm(q,lowPowerThreshold,base);			
			}						
		}catch (Exception e) {
			logger.error("processDevPowerData error :" + e.getMessage());
			return;
		}		
	}

	
	
	//v1版本,废弃
	private void judgeDevPowerAlarm_v1(int curPercent, float lowPowerThreshold , DevMeteData mete) {
		if(curPercent < lowPowerThreshold){
			AlarmData alarm = new AlarmData();
			alarm.setDeveui(mete.getDeveui());
			alarm.setDevtype(mete.getDevtype());
			alarm.setProjectid(mete.getProjectid());
			alarm.setTypeflag(AlarmData.TPFLAG_ALARM); 
			alarm.setAlarmlevel(AlarmData.ALARM_LEVEL_1);					
			alarm.setAlarmid("A"+Math.abs(UUID.randomUUID().getLeastSignificantBits()));
			alarm.setAlarmlevel(AlarmData.ALARM_LEVEL_1);
			alarm.setAlarmcode(LOW_POWER_ALARM_CODE);
			alarm.setTitle(LocUtils.getDevName(mete.getDeveui())+"-"+LOW_POWER_ALARM_DESC);			
			alarm.setDevname(LocUtils.getDevName(mete.getDeveui()));			
			alarm.setAlarmtime(new Timestamp(System.currentTimeMillis()));
			alarm.setDescp(LocUtils.getDevName(mete.getDeveui())+"-"+LOW_POWER_ALARM_DESC);
			alarm.setConfirmstate(AlarmData.CONFIRM_STATE_N);	
			// 发布告警.
			String alarmJson = JsonUtils.toJson(alarm);
			this.alarmPublisher.publishMessage(alarmJson);				
		}
	}
	
	
		
	//判定是否需要报警还是恢复告警
	private void judgeDevPowerAlarm(int curPercent, float lowPowerThreshold , DevPowerBase mete) {
		String devname = (mete.getDevname() != null) ? mete.getDevname() : mete.getDeveui();
		AlarmData alarm = null;
		
		if(curPercent < lowPowerThreshold){
			//如果缓存中没有报警或者报警已清除
			if(!checkAlarmExsit(mete)){
				//产生告警
				alarm = generateAlarm(mete);
				alarm.setTypeflag(AlarmData.TPFLAG_ALARM); 	
				alarm.setTitle(devname + "-" + LOW_POWER_ALARM_DESC);
				//更新缓存
				cacheManager.putLowPowerAlarmFlag(mete.getDeveui(), ALARM_FLAG);
			}							
		}else if(curPercent >= DEFAULT_NORMAL_POWER_THRESHOLD){
			//如果缓存中无报警或者报警未清除
			if(!checkAlarmClearExsit(mete)){
				//产生告警清除
				alarm = generateAlarm(mete);
				alarm.setTypeflag(AlarmData.TPFLAG_CLEAR); 	
				alarm.setTitle(devname + "-" + NORMAL_POWER_DESC);
				//更新缓存
				cacheManager.putLowPowerAlarmFlag(mete.getDeveui(), ALARM_CLEAR_FLAG);
			}
		}else{
			alarm = null;
		}
		
		if(alarm != null){
			String alarmJson = JsonUtils.toJson(alarm);
			this.alarmPublisher.publishMessage(alarmJson);			
		}
	}
	
	//检查报警是否存在
	private boolean checkAlarmExsit(DevPowerBase meta){
		String deveui = meta.getDeveui();
		if(deveui == null || deveui.equals("")){
			return false;
		}
		Integer flag = cacheManager.getLowPowerAlarmFlag(deveui);
		//报警存在:缓存中有记录且报警标记为0
		return (flag != null && ALARM_FLAG.equals(flag));
	}
	
	
	//检查报警是否恢复过
	private boolean checkAlarmClearExsit(DevPowerBase meta){
		String deveui = meta.getDeveui();
		if(deveui == null || deveui.equals("")){
			return false;
		}
		Integer flag = cacheManager.getLowPowerAlarmFlag(deveui);
		//报警清除:缓存中有记录且清除标记为1
		return (flag != null && ALARM_CLEAR_FLAG.equals(flag));
	}
	
	
	//生成报警对象
	private AlarmData generateAlarm(DevPowerBase mete){	
		AlarmData alarm = new AlarmData();
		alarm.setAlarmkey(AlarmUtils.generateAlarmKey(mete.getDeveui(), mete.getDevtype(), LOW_POWER_ALARM_CODE));
		alarm.setDeveui(mete.getDeveui());
		alarm.setDevtype(mete.getDevtype());
		alarm.setProjectid(mete.getProjectid());
		alarm.setAlarmid("A" + Math.abs(UUID.randomUUID().getLeastSignificantBits()));
		alarm.setAlarmlevel(AlarmData.ALARM_LEVEL_1);
		alarm.setAlarmcode(LOW_POWER_ALARM_CODE);
		alarm.setConfirmstate(AlarmData.CONFIRM_STATE_N);		
		return alarm;
	} 
		
	
}
